#!/usr/bin/env python3
"""
音频修复小工具 - FastAPI 后端主程序
提供音频上传、降噪处理、文件服务等功能
"""

import os
import uuid
import shutil
from typing import Optional
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
import logging

from audio_processor import AudioProcessor

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 创建FastAPI应用
app = FastAPI(
    title="音频修复小工具",
    description="智能音频降噪修复服务",
    version="1.0.0"
)

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 创建静态文件目录
STATIC_DIR = "backend/static"
UPLOAD_DIR = os.path.join(STATIC_DIR, "uploads")
PROCESSED_DIR = os.path.join(STATIC_DIR, "processed")

# 确保目录存在
os.makedirs(UPLOAD_DIR, exist_ok=True)
os.makedirs(PROCESSED_DIR, exist_ok=True)

# 挂载静态文件
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")

# 初始化音频处理器
audio_processor = AudioProcessor()


@app.get("/")
async def root():
    """根路径，返回服务状态"""
    return {
        "message": "音频修复小工具 API 服务运行中",
        "version": "1.0.0",
        "status": "active"
    }


@app.post("/process-audio")
async def process_audio(
    audio: UploadFile = File(...),
    mode: str = Form("auto"),
    noise_reduction: Optional[int] = Form(50)
):
    """
    处理音频文件
    
    Args:
        audio: 上传的音频文件
        mode: 处理模式 ("auto" 或 "manual")
        noise_reduction: 降噪强度 (0-100, 仅手动模式有效)
    
    Returns:
        处理后的文件URL和相关信息
    """
    try:
        # 验证文件类型
        allowed_types = ["audio/mpeg", "audio/wav", "audio/x-wav", "audio/mp4", "audio/m4a"]
        if audio.content_type not in allowed_types:
            raise HTTPException(status_code=400, detail="不支持的音频格式")
        
        # 生成唯一文件名
        file_id = str(uuid.uuid4())
        file_extension = os.path.splitext(audio.filename)[1] if audio.filename else ".mp3"
        original_filename = f"{file_id}_original{file_extension}"
        processed_filename = f"{file_id}_processed{file_extension}"
        
        original_path = os.path.join(UPLOAD_DIR, original_filename)
        processed_path = os.path.join(PROCESSED_DIR, processed_filename)
        
        # 保存原始文件
        logger.info(f"保存原始文件: {original_filename}")
        with open(original_path, "wb") as buffer:
            shutil.copyfileobj(audio.file, buffer)
        
        # 处理音频
        logger.info(f"开始处理音频，模式: {mode}")
        
        if mode == "auto":
            # 自动模式：使用默认参数
            success = audio_processor.auto_process(original_path, processed_path)
        else:
            # 手动模式：使用指定降噪强度
            reduction_strength = max(0, min(100, noise_reduction)) / 100.0
            success = audio_processor.manual_process(original_path, processed_path, reduction_strength)
        
        if not success:
            raise HTTPException(status_code=500, detail="音频处理失败")
        
        logger.info(f"音频处理完成: {processed_filename}")
        
        # 返回结果
        return {
            "success": True,
            "message": "音频处理成功",
            "original_url": f"/static/uploads/{original_filename}",
            "processed_url": f"/static/processed/{processed_filename}",
            "file_id": file_id,
            "mode": mode
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"音频处理错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"处理失败: {str(e)}")


@app.get("/audio-info/{file_id}")
async def get_audio_info(file_id: str):
    """
    获取音频文件信息
    
    Args:
        file_id: 文件ID
    
    Returns:
        音频文件信息
    """
    try:
        # 查找文件
        original_pattern = f"{file_id}_original.*"
        processed_pattern = f"{file_id}_processed.*"
        
        original_file = None
        processed_file = None
        
        for file in os.listdir(UPLOAD_DIR):
            if file.startswith(f"{file_id}_original"):
                original_file = file
                break
        
        for file in os.listdir(PROCESSED_DIR):
            if file.startswith(f"{file_id}_processed"):
                processed_file = file
                break
        
        if not original_file:
            raise HTTPException(status_code=404, detail="文件未找到")
        
        # 获取文件信息
        original_path = os.path.join(UPLOAD_DIR, original_file)
        file_stats = os.stat(original_path)
        
        return {
            "file_id": file_id,
            "original": {
                "filename": original_file,
                "url": f"/static/uploads/{original_file}",
                "size": file_stats.st_size
            },
            "processed": {
                "filename": processed_file,
                "url": f"/static/processed/{processed_file}" if processed_file else None
            } if processed_file else None
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取文件信息错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取信息失败: {str(e)}")


@app.delete("/cleanup/{file_id}")
async def cleanup_files(file_id: str):
    """
    清理指定文件ID的相关文件
    
    Args:
        file_id: 文件ID
    
    Returns:
        清理结果
    """
    try:
        deleted_files = []
        
        # 清理上传目录
        for file in os.listdir(UPLOAD_DIR):
            if file.startswith(file_id):
                file_path = os.path.join(UPLOAD_DIR, file)
                os.remove(file_path)
                deleted_files.append(file)
        
        # 清理处理目录
        for file in os.listdir(PROCESSED_DIR):
            if file.startswith(file_id):
                file_path = os.path.join(PROCESSED_DIR, file)
                os.remove(file_path)
                deleted_files.append(file)
        
        return {
            "success": True,
            "message": f"已清理 {len(deleted_files)} 个文件",
            "deleted_files": deleted_files
        }
        
    except Exception as e:
        logger.error(f"清理文件错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"清理失败: {str(e)}")


@app.get("/health")
async def health_check():
    """健康检查接口"""
    return {
        "status": "healthy",
        "timestamp": logger.handlers[0].baseFilename if logger.handlers else "active"
    }


if __name__ == "__main__":
    import uvicorn
    
    logger.info("启动音频修复小工具服务...")
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
        log_level="info"
    )
